﻿#include "pch.h"

CBuffer10Wrapper::CBuffer10Wrapper()
{
    memset((void *)this, 0, sizeof(CBuffer10Wrapper));
}

void CBuffer10Wrapper::printSelf(char *captionUpper, int32_t)
{
    char caption[1024];
    sprintf(caption, "%s:%s", captionUpper, "CBuffer10Wrapper");
    print4x(this, sizeof(CBuffer10Wrapper), caption);
    if (this->head)
    {
        sprintf(caption, "%s:%s", captionUpper, "CBuffer10Wrapper.head");
        print4x(this->head, this->size * this->len, caption);
    }
    if (this->num)
    {
        sprintf(caption, "%s:%s", captionUpper, "CBuffer10Wrapper.num");
        print4x(this->num, sizeof(int32_t), caption);
    }
}

// sub_1001B200
CBuffer10Wrapper *CBuffer10Wrapper::init(int32_t len)
{
    init_(len);
    return this;
};

// sub_1001E0A0
CBuffer10Wrapper *CBuffer10Wrapper::init_(int32_t len)
{
    this->needFreeHead = true;
    this->head = (LPVOID) new BYTE[sizeof(Buffer10) * len];
    if (this->head)
    {
        this->size = sizeof(Buffer10);
        this->len = len;
        memset((void *)this->head, 0, sizeof(Buffer10) * len);
        this->num = &(this->numValue);
        *(this->num) = 0;
        this->tail = 0;
    }
    return this;
};

// sub_100010BE
CBuffer10Wrapper *CBuffer10Wrapper::clean()
{
    this->clearHead();
    this->sumCounter = 0;
    this->sumHeight = 0;
    this->sumArea = 0;
    this->normalDiffH05 = 0;
    this->type0Counter = 0;
    this->type2Counter = 0;
    this->type1Counter = 0;
    this->cleanCalcUnit1();
    return this->cleanCalcUnit2();
};

// sub_100196E0
CBuffer10Wrapper *CBuffer10Wrapper::cleanCalcUnit1()
{
    this->calcUnit1.timeEnd = 0;
    this->calcUnit1.timeStart = 0;
    this->calcUnit1.heightStart = 0;
    this->calcUnit1.area = 0;
    return this;
};

// sub_10019720
CBuffer10Wrapper *CBuffer10Wrapper::cleanCalcUnit2()
{
    this->calcUnit2.timeEnd = 0;
    this->calcUnit2.timeStart = 0;
    this->calcUnit2.heightStart = 0;
    this->calcUnit2.area = 0;
    return this;
};

// sub_1001BA60
double CBuffer10Wrapper::getNormalDiffH05()
{
    return this->normalDiffH05;
};

// sub_10001738
int32_t CBuffer10Wrapper::setCalcUnit1(TDLLResultListItem *pRes, float normalizeSlope)
{
    if (this->calcUnit1.timeStart > 0 && this->calcUnit1.timeEnd > 0)
    {
        return true;
    }
    if (this->calcUnit1.timeStart)
    {
        if (!this->calcUnit1.timeEnd)
        {
            this->setCalcUnitValue1(&this->calcUnit1, pRes, normalizeSlope);
        }
    }
    else
    {
        this->setCalcUnitStartTime1(&this->calcUnit1, pRes, normalizeSlope);
    }
    return false;
};

// sub_10001A80
int32_t CBuffer10Wrapper::setCalcUnit2(TDLLResultListItem *pRes, float normalizeSlope)
{
    if (this->calcUnit2.timeStart > 0 && this->calcUnit2.timeEnd > 0)
    {
        return true;
    }
    if (this->calcUnit2.timeStart)
    {
        if (!this->calcUnit2.timeEnd)
        {
            this->setCalcUnitValue2(&this->calcUnit2, pRes, normalizeSlope);
        }
    }
    else
    {
        this->setCalcUnitStartTime2(&this->calcUnit2, pRes, normalizeSlope);
    }
    return false;
};

// sub_10001560
int32_t CBuffer10Wrapper::setCalcUnitValue1(CalcUnit *cu, TDLLResultListItem *, float normalizeSlope)
{
    int32_t result;
    int32_t i;
    int32_t bufferNo;
    float diffH12;
    float diffH01;
    float ddslope;
    float diffH45;
    float diffH34;
    float diffH23;

    Buffer10 *pBuf = (Buffer10 *)this->head;

    if (cu->timeEnd > 0)
    {
        return true;
    }
    if (cu->timeStart >= pBuf[9].time)
    {
        diffH01 = pBuf[0].height - pBuf[1].height;
        diffH12 = pBuf[1].height - pBuf[2].height;
        diffH23 = pBuf[2].height - pBuf[3].height;
        diffH34 = pBuf[3].height - pBuf[4].height;
        ddslope = (diffH01 - diffH34) / (pBuf[0].time - pBuf[3].time);
        if (ddslope <= normalizeSlope || diffH01 <= diffH12 || diffH12 <= diffH23 || diffH23 <= diffH34 || (diffH45 = pBuf[4].height - pBuf[5].height, diffH34 >= diffH45) || diffH34 <= 0.0)
        {
            result = false;
        }
        else
        {
            bufferNo = 3;
            if (pBuf[3].time > cu->timeStart)
            {
                for (i = 3; i < 10 && pBuf[i].time > cu->timeStart && i != 9; ++i)
                {
                    ;
                }
                bufferNo = (i + 3) / 2;
            }
            cu->timeEnd = pBuf[bufferNo].time;
            cu->heightStart = pBuf[bufferNo].height;
            cu->area = pBuf[bufferNo].area;
            result = true;
        }
    }
    else
    {
        cu->timeStart = 0;
        result = false;
    }
    return result;
};

// sub_100018A8
int32_t CBuffer10Wrapper::setCalcUnitValue2(CalcUnit *cu, TDLLResultListItem *, float normalizeSlope)
{
    int32_t result;
    int32_t i;
    int32_t bufferNo;
    float diffH12;
    float diffH01;
    float ddslope;
    float diffH45;
    float diffH34;
    float diffH23;

    Buffer10 *pBuf = (Buffer10 *)this->head;

    if (cu->timeEnd > 0)
    {
        return true;
    }
    if (cu->timeStart >= pBuf[9].time)
    {
        diffH01 = pBuf[0].height - pBuf[1].height;
        diffH12 = pBuf[1].height - pBuf[2].height;
        diffH23 = pBuf[2].height - pBuf[3].height;
        diffH34 = pBuf[3].height - pBuf[4].height;
        ddslope = (diffH34 - diffH01) / (pBuf[0].time - pBuf[3].time);
        if (ddslope <= normalizeSlope || diffH01 >= diffH12 || diffH12 >= diffH23 || diffH23 >= diffH34 || (diffH45 = pBuf[4].height - pBuf[5].height, diffH34 <= diffH45) || diffH34 >= 0.0)
        {
            result = false;
        }
        else
        {
            bufferNo = 3;
            if (pBuf[3].time > cu->timeStart)
            {
                for (i = 3; i < 10 && pBuf[i].time > cu->timeStart && i != 9; ++i)
                {
                    ;
                }
                bufferNo = (i + 3) / 2;
            }
            cu->timeEnd = pBuf[bufferNo].time;
            cu->heightStart = pBuf[bufferNo].height;
            cu->area = pBuf[bufferNo].area;
            result = true;
        }
    }
    else
    {
        cu->timeStart = 0;
        result = false;
    }
    return result;
};

// sub_1000145D
int32_t CBuffer10Wrapper::setCalcUnitStartTime1(CalcUnit *cu, TDLLResultListItem *, float normalizeSlope)
{
    float ddslope;
    float diffH01;
    float diffH12;
    float diffH23;
    float diffH34;
    float diffH45;

    Buffer10 *pBuf = (Buffer10 *)this->head;

    if (cu->timeStart > 0)
    {
        return true;
    }
    diffH12 = pBuf[1].height - pBuf[2].height;
    diffH23 = pBuf[2].height - pBuf[3].height;
    diffH34 = pBuf[3].height - pBuf[4].height;
    diffH45 = pBuf[4].height - pBuf[5].height;
    ddslope = (diffH45 - diffH12) / (pBuf[1].time - pBuf[4].time);
    if (ddslope <= normalizeSlope)
    {
        return false;
    }
    diffH01 = pBuf[0].height - pBuf[1].height;
    if (diffH01 <= diffH12)
    {
        return false;
    }
    if (diffH12 >= diffH23)
    {
        return false;
    }
    if (diffH23 >= diffH34)
    {
        return false;
    }
    if (diffH34 >= diffH45 || diffH12 <= 0.0)
    {
        return false;
    }
    cu->timeStart = pBuf[1].time;
    return true;
};

// sub_100017A2
int32_t CBuffer10Wrapper::setCalcUnitStartTime2(CalcUnit *cu, TDLLResultListItem *, float normalizeSlope)
{
    float diffH01;
    float diffH12;
    float diffH23;
    float diffH34;
    float diffH45;
    float ddslope;

    Buffer10 *pBuf = (Buffer10 *)this->head;

    if (cu->timeStart > 0)
    {
        return true;
    }
    diffH12 = pBuf[1].height - pBuf[2].height;
    diffH23 = pBuf[2].height - pBuf[3].height;
    diffH34 = pBuf[3].height - pBuf[4].height;
    diffH45 = pBuf[4].height - pBuf[5].height;
    ddslope = (diffH12 - diffH45) / (pBuf[1].time - pBuf[4].time);
    if (ddslope <= normalizeSlope)
    {
        return false;
    }
    diffH01 = pBuf[0].height - pBuf[1].height;
    if (diffH01 >= diffH12 || diffH12 <= diffH23 || diffH23 <= diffH34 || diffH34 <= diffH45 || diffH12 >= 0.0)
    {
        return false;
    }
    cu->timeStart = pBuf[1].time;
    return true;
};

// unknown_libname_2
int32_t CBuffer10Wrapper::getUnit1TimeEnd()
{
    return this->calcUnit1.timeEnd;
};

// sub_1001A550
double CBuffer10Wrapper::getUnit1Height()
{
    return this->calcUnit1.heightStart;
    ;
};

// sub_1001A570
double CBuffer10Wrapper::getUnit1Area()
{
    return this->calcUnit1.area;
};

// sub_10019D60
int32_t CBuffer10Wrapper::getBuffer10Time(int32_t idx)
{
    Buffer10 *pBuf = (Buffer10 *)this->head;
    return pBuf[idx].time;
};

// sub_100197D0
double CBuffer10Wrapper::getBuffer10Height(int32_t idx)
{
    Buffer10 *pBuf = (Buffer10 *)this->head;
    return pBuf[idx].height;
};

// sub_1001A200
double CBuffer10Wrapper::getBuffer10Area(int32_t idx)
{
    Buffer10 *pBuf = (Buffer10 *)this->head;
    return pBuf[idx].area;
};

// sub_1001B9A0
int32_t CBuffer10Wrapper::checkType2Counter(int32_t checkType2)
{
    int32_t result;

    if (checkType2)
    {
        result = this->type2Counter > this->type1Counter + this->type0Counter;
    }
    else
    {
        result = this->type1Counter > this->type2Counter + this->type0Counter;
    }
    return result;
};

// sub_1001BAE0
int32_t CBuffer10Wrapper::checkType1Counter(int32_t checkType1)
{
    int32_t result;

    if (checkType1)
    {
        result = this->type1Counter > this->type2Counter + this->type0Counter;
    }
    else
    {
        result = this->type2Counter > this->type1Counter + this->type0Counter;
    }
    return result;
};

// sub_10001392
int32_t CBuffer10Wrapper::accBuffer10Value(int32_t time, int32_t val, int32_t groupCount, int32_t factor)
{
    Buffer10 *pBuf = (Buffer10 *)this->head;

    this->sumHeight += val / factor;
    this->sumArea = (double)val / (double)factor + this->sumArea;
    if (++this->sumCounter < groupCount)
    {
        return false;
    }
    memmove((void *)&pBuf[1], (void *)&pBuf[0], this->size * (this->len - 1));
    pBuf[0].area = this->sumArea;
    pBuf[0].height = (float)((double)this->sumHeight / (double)groupCount);
    pBuf[0].time = time;
    this->sumCounter = 0;
    this->setNormalDiffH05();
    this->sumHeight = 0;
    return true;
};

// sub_100197F0
CBuffer10Wrapper *CBuffer10Wrapper::setNormalDiffH05()
{
    double diffHeight05; // st7
    diffHeight05 = this->getBuffer10DiffHeight(0, 5);
    this->normalDiffH05 = (float)(diffHeight05 / 5.0);
    return this;
};

// sub_100197A0
double CBuffer10Wrapper::getBuffer10DiffHeight(int32_t bufferNo1, int32_t bufferNo2)
{
    Buffer10 *pBuf = (Buffer10 *)this->head;
    return pBuf[bufferNo1].height - pBuf[bufferNo2].height;
};

// sub_1001A980
int32_t CBuffer10Wrapper::getBuffer10DiffTime(int32_t bufferNo1, int32_t bufferNo2)
{
    Buffer10 *pBuf = (Buffer10 *)this->head;
    return pBuf[bufferNo1].time - pBuf[bufferNo2].time;
};

// sub_10001318
void CBuffer10Wrapper::deductArea(int32_t diploidTime, int32_t moreTime, int32_t *pDarea)
{
    int32_t i;

    Buffer10 *pBuf = (Buffer10 *)this->head;

    for (i = pBuf[0].time; i > pBuf[0].time - diploidTime / 2; --i)
    {
        pBuf[0].area = pBuf[0].area - pDarea[i];
    }
    pBuf[0].time -= (diploidTime + moreTime - 1) / 2;
};

// sub_1000112E
void CBuffer10Wrapper::countBuffer10Type(float horizValue)
{
    int32_t buffer10Type;
    float diffH01;
    int32_t i;

    diffH01 = (float)this->getBuffer10DiffHeight(0, 1);
    if (diffH01 <= horizValue)
    {
        if (-horizValue <= diffH01)
        {
            this->setBuffer10Type(0, 0);
        }
        else
        {
            this->setBuffer10Type(0, 2);
        }
    }
    else
    {
        this->setBuffer10Type(0, 1);
    }
    this->type2Counter = 0;
    this->type1Counter = 0;
    this->type0Counter = 0;
    for (i = 0; i < 5; ++i)
    {
        buffer10Type = this->getBuffer10Type(i);
        if (buffer10Type == 1)
        {
            ++this->type1Counter;
        }
        else if (buffer10Type == 2)
        {
            ++this->type2Counter;
        }
        else
        {
            ++this->type0Counter;
        }
    }
};

// sub_10019760
void CBuffer10Wrapper::setBuffer10Type(int32_t bufferNo, int32_t type)
{
    Buffer10 *pBuf = (Buffer10 *)this->head;
    pBuf[bufferNo].type = type;
};

// sub_10019780
int32_t CBuffer10Wrapper::getBuffer10Type(int32_t bufferNo)
{
    Buffer10 *pBuf = (Buffer10 *)this->head;
    return pBuf[bufferNo].type;
};

// sub_10019D80
int32_t CBuffer10Wrapper::hasSalientPoint(float minHDiff)
{
    int32_t result;
    Buffer10 *pBuf = (Buffer10 *)this->head;

    if (pBuf[9].time <= 0 || this->normalDiffH05 < minHDiff)
    {
        result = false;
    }
    else
    {
        if (this->type1Counter > this->type2Counter + this->type0Counter)
        {
            return true;
        }
        if (this->checkCurvature(0))
        {
            return true;
        }
        if (this->isDiffH10Exceed(0))
        {
            result = true;
        }
        else
        {
            result = false;
        }
    }
    return result;
};

// sub_10019E50
int32_t CBuffer10Wrapper::hasSalientPointType2(float maxDiff)
{
    int32_t result;
    Buffer10 *pBuf = (Buffer10 *)this->head;

    if (pBuf[9].time <= 0 || this->normalDiffH05 >= maxDiff)
    {
        result = false;
    }
    else
    {
        if (this->type2Counter == 5)
        {
            return true;
        }
        if (this->checkCurvature(1))
        {
            return true;
        }
        if (this->isDiffH10Exceed(1))
        {
            result = true;
        }
        else
        {
            result = false;
        }
    }
    return result;
};

// sub_10019EC0
int32_t CBuffer10Wrapper::checkCurvature(int32_t positive)
{
    int32_t result;
    float H4;
    float H3;
    float H2;
    float H1;
    float H0;

    Buffer10 *pBuf = (Buffer10 *)this->head;

    H0 = pBuf[0].height;
    H1 = pBuf[1].height;
    H2 = pBuf[2].height;
    H3 = pBuf[3].height;
    H4 = pBuf[4].height;
    if (positive)
    {
        result = 2.0 * H3 > 1.0 * H2 + H4 && 3.0 * H2 > 2.0 * H2 + H4 && 4.0 * H1 > 3.0 * H0 + H4;
    }
    else
    {
        result = 2.0 * H3 < 1.0 * H2 + H4 && 3.0 * H2 < 2.0 * H1 + H4 && 4.0 * H1 < 3.0 * H0 + H4;
    }
    return result;
};

// sub_10019E00
int32_t CBuffer10Wrapper::isDiffH10Exceed(int32_t negative)
{
    float diffH01;

    diffH01 = (float)this->getBuffer10DiffHeight(0, 1);
    if (negative)
    {
        diffH01 = -diffH01;
    }
    return diffH01 > 32000.0;
};

// sub_10001297
int32_t CBuffer10Wrapper::searchMaximalHeightIndex(int32_t tailIndex, int32_t headIndex)
{
    int32_t i;
    float maxHeight;

    if (tailIndex < 0)
    {
        tailIndex = 0;
    }
    if (tailIndex > 9)
    {
        tailIndex = 9;
    }
    i = tailIndex;
    maxHeight = (float)this->getBuffer10Height(tailIndex);
    while (i >= headIndex)
    {
        if (this->getBuffer10Height(i) > maxHeight)
        {
            maxHeight = (float)this->getBuffer10Height(i);
            tailIndex = i;
        }
        --i;
    }
    return tailIndex;
};

// sub_10001216
int32_t CBuffer10Wrapper::searchMinimalHeightIndex(int32_t tailIndex, int32_t headIndex)
{
    int32_t i;
    float minHeight;

    if (tailIndex < 0)
    {
        tailIndex = 0;
    }
    if (tailIndex > 9)
    {
        tailIndex = 9;
    }
    i = tailIndex;
    minHeight = (float)this->getBuffer10Height(tailIndex);
    while (i >= headIndex)
    {
        if (this->getBuffer10Height(i) < minHeight)
        {
            minHeight = (float)this->getBuffer10Height(i);
            tailIndex = i;
        }
        --i;
    }
    return tailIndex;
};

// sub_1001A590
int32_t CBuffer10Wrapper::getUnit2TimeEnd()
{
    return this->calcUnit2.timeEnd;
};

// sub_1001A5B0
double CBuffer10Wrapper::getUnit2Height()
{
    return this->calcUnit2.heightStart;
};

// sub_1001A5D0
int32_t CBuffer10Wrapper::getType1Counter()
{
    return this->type1Counter;
};

// sub_1001C550
int32_t CBuffer10Wrapper::checkType0Counter()
{
    return this->type0Counter > this->type2Counter + this->type1Counter;
};

// sub_1001BD60
int32_t CBuffer10Wrapper::isDiffHeightExceedThreshold(int32_t threshold)
{
    float diffThreshold;
    float diffH23;
    float diffH12;
    float diffH01;

    diffThreshold = (float)(threshold * 6400.0);
    diffH01 = (float)this->getBuffer10DiffHeight(0, 1);
    diffH12 = (float)this->getBuffer10DiffHeight(1, 2);
    diffH23 = (float)this->getBuffer10DiffHeight(2, 3);
    return diffH01 > diffThreshold && diffH12 > diffThreshold && diffH23 > diffThreshold;
};
